package sk.uniba.fmph.asdf.gui.frames;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import sk.uniba.fmph.asdf.Session;
import sk.uniba.fmph.asdf.db.Account;
import sk.uniba.fmph.asdf.db.AccountManager;
import sk.uniba.fmph.asdf.db.FullName;
import sk.uniba.fmph.asdf.exceptions.DatabaseException;
import sk.uniba.fmph.asdf.exceptions.PermissionDeniedException;
import sk.uniba.fmph.asdf.gui.views.MainView;

/**
 *
 * @author Jakub Gaľ
 * @author Matej
 */
public class AccountEditorFrame extends Frame implements ActionListener {

	private static final long serialVersionUID = -3441002455527062627L;
	private javax.swing.JButton buttonDeleteAccount;
	private javax.swing.JButton buttonSaveAccount;
	private javax.swing.JLabel labelEmail;
	private javax.swing.JLabel labelFirstName;
	private javax.swing.JLabel labelPassword;
	private javax.swing.JLabel labelSurname;
	private javax.swing.JPanel panelAccountDetails;
	private javax.swing.JPanel panelCenter;
	private javax.swing.JPanel panelLeft;
	private javax.swing.JPanel panelRight;
	private javax.swing.JPasswordField passwordField;
	private javax.swing.JScrollPane scrollPaneAccounts;
	private javax.swing.JTextField textFieldEmail;
	private javax.swing.JTextField textFieldFirstName;
	private javax.swing.JTextField textFieldSurname;
	private javax.swing.JTree treeAccounts;
	Account selectedAccount;
	TreePath selectedPath;

	/**
	 * Vytvori view, inicializuje komponenty a nastavi podtitulok okna.
	 */
	public AccountEditorFrame(MainView parent) {
		super(parent);
		initComponents();
	}

	@Override
	public void onShow() {
		//parent.setSubtitle("Správa účtu");
	}

	/**
	 * Inicializacia komponentov
	 */
	private void initComponents() {
		setMinimumSize(new java.awt.Dimension(800, 600));
		setPreferredSize(new java.awt.Dimension(800, 600));
		setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));

		panelLeft = new javax.swing.JPanel();
		scrollPaneAccounts = new javax.swing.JScrollPane();
		treeAccounts = new javax.swing.JTree();
		panelCenter = new javax.swing.JPanel();
		panelAccountDetails = new javax.swing.JPanel();
		labelFirstName = new javax.swing.JLabel();
		textFieldFirstName = new javax.swing.JTextField();
		labelSurname = new javax.swing.JLabel();
		textFieldSurname = new javax.swing.JTextField();
		labelEmail = new javax.swing.JLabel();
		textFieldEmail = new javax.swing.JTextField();
		labelPassword = new javax.swing.JLabel();
		passwordField = new javax.swing.JPasswordField();
		panelRight = new javax.swing.JPanel();
		buttonSaveAccount = new javax.swing.JButton();
		buttonDeleteAccount = new javax.swing.JButton();

		buttonSaveAccount.addActionListener(this);
		buttonDeleteAccount.addActionListener(this);

		panelLeft.setPreferredSize(new java.awt.Dimension(175, 600));
		panelLeft.setMaximumSize(new java.awt.Dimension(175, Integer.MAX_VALUE));
		panelLeft.setLayout(new javax.swing.BoxLayout(panelLeft, javax.swing.BoxLayout.PAGE_AXIS));

		generateAccountTree();
		scrollPaneAccounts.setViewportView(treeAccounts);
		treeAccounts.getSelectionModel().setSelectionMode(javax.swing.tree.TreeSelectionModel.SINGLE_TREE_SELECTION);
		treeAccounts.setSelectionRow(1);
		selectAccount(Session.getAccount());

		treeAccounts.addTreeSelectionListener(new TreeSelectionListener() {
			@Override
			public void valueChanged(TreeSelectionEvent e) {
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeAccounts.getLastSelectedPathComponent();
				if (node != null && (node.getUserObject() instanceof Account)) {
					selectedPath = treeAccounts.getSelectionPath();
					Account nodeInfo = (Account) node.getUserObject();

					selectAccount(nodeInfo);
				}
			}
		});

		panelLeft.add(scrollPaneAccounts);

		add(panelLeft);

		panelCenter.setBorder(javax.swing.BorderFactory.createEtchedBorder());
		panelCenter.setPreferredSize(new java.awt.Dimension(450, 600));
		panelCenter.setLayout(new java.awt.BorderLayout());

		labelFirstName.setText("Krstné meno");
		labelSurname.setText("Priezvisko");
		labelEmail.setText("E-mail");
		labelPassword.setText("Heslo");

		javax.swing.GroupLayout panelAccountDetailsLayout = new javax.swing.GroupLayout(panelAccountDetails);
		panelAccountDetails.setLayout(panelAccountDetailsLayout);
		panelAccountDetailsLayout.setHorizontalGroup(
						panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(panelAccountDetailsLayout.createSequentialGroup()
						.addGap(121, 121, 121)
						.addGroup(panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
						.addComponent(labelFirstName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(labelPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(labelEmail, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(labelSurname, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 42, Short.MAX_VALUE)
						.addGroup(panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
						.addComponent(textFieldSurname, javax.swing.GroupLayout.Alignment.TRAILING)
						.addComponent(textFieldEmail, javax.swing.GroupLayout.Alignment.TRAILING)
						.addComponent(passwordField, javax.swing.GroupLayout.Alignment.TRAILING)
						.addComponent(textFieldFirstName, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE))
						.addGap(123, 123, 123)));
		panelAccountDetailsLayout.setVerticalGroup(
						panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(panelAccountDetailsLayout.createSequentialGroup()
						.addContainerGap()
						.addGroup(panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
						.addComponent(labelFirstName, javax.swing.GroupLayout.Alignment.TRAILING)
						.addComponent(textFieldFirstName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addGroup(panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
						.addComponent(labelSurname, javax.swing.GroupLayout.Alignment.TRAILING)
						.addComponent(textFieldSurname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addGroup(panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
						.addComponent(textFieldEmail, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
						.addComponent(labelEmail))
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addGroup(panelAccountDetailsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
						.addComponent(passwordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
						.addComponent(labelPassword))
						.addContainerGap(487, Short.MAX_VALUE)));

		panelCenter.add(panelAccountDetails, java.awt.BorderLayout.CENTER);

		add(panelCenter);

		panelRight.setMaximumSize(new java.awt.Dimension(175, Integer.MAX_VALUE));
		panelRight.setPreferredSize(new java.awt.Dimension(175, 600));
		panelRight.setLayout(new java.awt.GridLayout(0, 1));

		buttonSaveAccount.setText("Uložiť údaje");
		buttonDeleteAccount.setText("Zmazať účet");

		panelRight.add(buttonSaveAccount);
		panelRight.add(buttonDeleteAccount);

		add(panelRight);
	}

	/**
	 * Nastavi stavovu premennu aktualne zvoleneho uctu a vyplni editacne polia.
	 *
	 * @param account
	 */
	private void selectAccount(Account account) {
		if (account != null) {
			selectedAccount = account;
			textFieldEmail.setText(selectedAccount.getEmail());
			textFieldFirstName.setText(selectedAccount.getFullName().getFirstName());
			textFieldSurname.setText(selectedAccount.getFullName().getLastName());
		}
	}

	/**
	 * Generuje strom uctov, pre bezneho pouzivatela zo sessionu, pre admina z
	 * databazy.
	 */
	private void generateAccountTree() {
		// root
		javax.swing.tree.DefaultMutableTreeNode treeNodeRoot = new javax.swing.tree.DefaultMutableTreeNode("Správa účtov");
		if (Session.getAccount() != null) {
			// my account
			javax.swing.tree.DefaultMutableTreeNode treeNodeAccounts = null;
			if (Session.getAccount().isAdmin()) {
				try {
					java.util.ArrayList<Account> accounts;
					accounts = AccountManager.getUsers();
					treeNodeAccounts = new javax.swing.tree.DefaultMutableTreeNode("Ostatní používatelia");
					for (Account a : accounts) {
						if (a.equals(Session.getAccount())) {
							continue;
						}
						javax.swing.tree.DefaultMutableTreeNode treeNodeAccount = new javax.swing.tree.DefaultMutableTreeNode(a);
						treeNodeAccounts.add(treeNodeAccount);
					}
				} catch (DatabaseException e) {
					e.printStackTrace();
				}
			} else {
				treeNodeAccounts = new javax.swing.tree.DefaultMutableTreeNode(Session.getAccount());
			}
			treeNodeRoot.add(treeNodeAccounts);
		}
		treeAccounts.setModel(new javax.swing.tree.DefaultTreeModel(treeNodeRoot));
		treeAccounts.setSelectionRow(1);
	}

	/**
	 * Metoda zavola metody AccountManageru pre zmenu uctu a nastavi novy ucet do
	 * sessionu.
	 *
	 * @param evt udalost vyvolana na prislusnom tlacitku
	 */
	public void buttonSaveAccountActionPerformed(java.awt.event.ActionEvent evt) {
		try {
			if (Session.getAccount() == null) {
				return;
			}
			if (textFieldFirstName.getText().equals("") || textFieldSurname.getText().equals("")
							|| textFieldEmail.getText().equals("")) {
				JOptionPane.showMessageDialog(parent, "Je potrebné vyplniť všetky údaje.", "Chyba!", JOptionPane.ERROR_MESSAGE);
				return;
			}
			if (Session.getAccount().isAdmin() && selectedAccount == null) {
				return;
			}
			Pattern validEmail = Pattern.compile("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+"
							+ "(\\.[a-z0-9-]+)*(\\.[a-z]{2,4})$");
			if (!validEmail.matcher(textFieldEmail.getText()).matches()) {
				JOptionPane.showMessageDialog(parent, "Nesprávny formát e-mailu.", "Chyba!", JOptionPane.ERROR_MESSAGE);
				return;
			}
			int id = (Session.getAccount().isAdmin()) ? selectedAccount.getId() : Session.getAccount().getId();
			FullName fn = new FullName(textFieldFirstName.getText(), textFieldSurname.getText());

			if (parent.synchronizeLocalFiles() && parent.synchronizeWithDB()) {
				AccountManager.editUserDetails(id, textFieldEmail.getText(), fn);
				if (String.valueOf(passwordField.getPassword()).length() > 0) {
					if (String.valueOf(passwordField.getPassword()).length() > 4) {
						AccountManager.editUserPassword(id, new String(passwordField.getPassword()));
					} else {
						JOptionPane.showMessageDialog(parent, "Heslo musí obsahovať aspoň 5 znakov.", "Chyba!", JOptionPane.ERROR_MESSAGE);
					}
				}
				Account a = AccountManager.getUser(id);
				Session.setAccount(a);
				parent.setAccount(a.getEmail());
			}
		} catch (DatabaseException e) {
			JOptionPane.showMessageDialog(parent, "Problém s databázou.", "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (PermissionDeniedException e) {
			JOptionPane.showMessageDialog(parent, "Nedostatočné privilégiá.", "Chyba!", JOptionPane.ERROR_MESSAGE);
		}
	}

	/**
	 * Metoda vymaze zvoleny ucet pomocou AccountManageru a prekresli strom uctov.
	 *
	 * @param evt udalost vyvolana na prislusnom tlacitku
	 */
	public void buttonDeleteAccountActionPerformed(java.awt.event.ActionEvent evt) {
		try {
			if (Session.getAccount() == null) {
				return;
			}
			if (!Session.getAccount().isAdmin()) {
				JOptionPane.showMessageDialog(parent, "Vymazávať účty môže len administrátor.", "Chyba!", JOptionPane.ERROR_MESSAGE);
				return;
			}
			if (Session.getAccount().getId() == selectedAccount.getId()) {
				JOptionPane.showMessageDialog(parent, "Administrátorské konto sa nedá vymazať.", "Chyba!", JOptionPane.ERROR_MESSAGE);
				return;
			}
			AccountManager.deleteUser(selectedAccount.getId());
			/* TODO update tree */
			treeAccounts.removeSelectionPath(selectedPath);
		} catch (DatabaseException e) {
			JOptionPane.showMessageDialog(parent, "Problém s databázou.", "Chyba!", JOptionPane.ERROR_MESSAGE);
		} catch (PermissionDeniedException e) {
			JOptionPane.showMessageDialog(parent, "Nedostatočné privilégiá.", "Chyba!", JOptionPane.ERROR_MESSAGE);
		}
	}

	/**
	 * Spracovanie kliknuti na tlacitka.
	 *
	 * @param arg0
	 */
	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == buttonSaveAccount) {
			buttonSaveAccountActionPerformed(arg0);
		} else if (arg0.getSource() == buttonDeleteAccount) {
			buttonDeleteAccountActionPerformed(arg0);
		}
	}
}